package com.ws.schedule;

import com.service.ChatMessageService;
import com.ws.MessageManager;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

import static com.ws.MessageManager.CHAT_TTL;

@Slf4j
@Component
public class MessageSync {
    private static final String SYNC_REDIS_CACHE_LOCK = "sync:redis:cache:lock";
    private static final String SCHEDULE_SYNC_REDIS = "schedule:sync:lock";
    private final StringRedisTemplate stringRedisTemplate;
    private final RedissonClient redissonClient;
    private final MessageManager messageManager;

    private final ChatMessageService chatMessageService;

    @Autowired
    public MessageSync(RedissonClient redissonClient, MessageManager messageManager, StringRedisTemplate stringRedisTemplate, ChatMessageService chatMessageService) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.redissonClient = redissonClient;
        this.chatMessageService = chatMessageService;
        this.messageManager = messageManager;
    }

    @Scheduled(fixedDelay = 1000 * 60)
    public void syncRedisCache() {
        RLock lock1 = redissonClient.getLock(SCHEDULE_SYNC_REDIS);
        try {
            if (lock1.tryLock()) {
                Cursor<String> scan = stringRedisTemplate.scan(ScanOptions.scanOptions().match("private" + "*").build());
                while (scan.hasNext()) {
                    String next = scan.next();
                    Long expire = stringRedisTemplate.getExpire(next, TimeUnit.MINUTES);
                    if (expire != null && expire <= CHAT_TTL / 3) {
                        RLock lock = redissonClient.getLock(SYNC_REDIS_CACHE_LOCK + next);
                        try {
                            if (lock.tryLock(0, 30, TimeUnit.SECONDS)) {
                                messageManager.syncRedisCache(next, 0L, (int) System.currentTimeMillis());
                            }
                        } catch (InterruptedException e) {
                            log.error("定时任务同步数据失败", e);
                            throw new RuntimeException(e);
                        } finally {
                            lock.unlock();
                        }
                    }
                }
            }
        } finally {
            lock1.unlock();
        }
    }    @Scheduled(fixedDelay = 1000 * 60)
    public void syncRedisCache1() {
        RLock lock1 = redissonClient.getLock(SCHEDULE_SYNC_REDIS);
        try {
            if (lock1.tryLock()) {
                Cursor<String> scan = stringRedisTemplate.scan(ScanOptions.scanOptions().match("group" + "*").build());
                while (scan.hasNext()) {
                    String next = scan.next();
                    Long expire = stringRedisTemplate.getExpire(next, TimeUnit.MINUTES);
                    if (expire != null && expire <= CHAT_TTL / 3) {
                        RLock lock = redissonClient.getLock(SYNC_REDIS_CACHE_LOCK + next);
                        try {
                            if (lock.tryLock(0, 30, TimeUnit.SECONDS)) {
                                messageManager.syncRedisCache(next, 0L, (int) System.currentTimeMillis());
                            }
                        } catch (InterruptedException e) {
                            log.error("定时任务同步数据失败", e);
                            throw new RuntimeException(e);
                        } finally {
                            lock.unlock();
                        }
                    }
                }
            }
        } finally {
            lock1.unlock();
        }
    }
}
